package org.luckystrophe.snowtoms.fragment;

import java.io.IOException;

import kr.hyosang.coordinate.CoordPoint;
import kr.hyosang.coordinate.TransCoord;
import net.daum.mf.map.api.MapPOIItem;
import net.daum.mf.map.api.MapPoint;
import net.daum.mf.map.api.MapPoint.GeoCoordinate;
import net.daum.mf.map.api.MapReverseGeoCoder;
import net.daum.mf.map.api.MapView;
import net.daum.mf.map.api.MapView.CurrentLocationEventListener;

import org.apache.http.client.ClientProtocolException;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.luckystrophe.snowtoms.R;
import org.luckystrophe.snowtoms.manager.GeocodeManager;
import org.luckystrophe.snowtoms.model.CoachMarks;
import org.luckystrophe.snowtoms.model.JsonRequest;
import org.luckystrophe.snowtoms.model.impl.AddressSearchRequest;
import org.luckystrophe.snowtoms.model.impl.CoachMarksImpl;
import org.luckystrophe.snowtoms.model.impl.District;
import org.luckystrophe.snowtoms.model.impl.RequestSnowboxes;
import org.luckystrophe.snowtoms.pref.AppPreference_;
import org.luckystrophe.snowtoms.pref.SnowtomsPreference;

import android.content.Context;
import android.content.Intent;
import android.graphics.drawable.AnimationDrawable;
import android.location.Criteria;
import android.location.Location;
import android.location.LocationListener;
import android.location.LocationManager;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import com.actionbarsherlock.app.SherlockFragment;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.widget.SearchView.OnQueryTextListener;
import com.googlecode.androidannotations.annotations.AfterInject;
import com.googlecode.androidannotations.annotations.AfterViews;
import com.googlecode.androidannotations.annotations.Background;
import com.googlecode.androidannotations.annotations.Bean;
import com.googlecode.androidannotations.annotations.Click;
import com.googlecode.androidannotations.annotations.EFragment;
import com.googlecode.androidannotations.annotations.UiThread;
import com.googlecode.androidannotations.annotations.ViewById;
import com.googlecode.androidannotations.annotations.sharedpreferences.Pref;

@EFragment(R.layout.fragment_info)
public class INFOFragment extends SherlockFragment implements MapView.OpenAPIKeyAuthenticationResultListener,
		MapView.MapViewEventListener, MapView.POIItemEventListener, OnQueryTextListener, CurrentLocationEventListener,
		LocationListener {

	@Bean
	GeocodeManager geoManager;

	@Bean(AddressSearchRequest.class)
	JsonRequest addressSearchRequest;

	// @Bean(SnowBoxJson.class)
	// JsonRequest snowBoxJson;

	@ViewById(R.id.mv_daum)
	MapView mapView;

	@ViewById(R.id.btn_getcenterpoint)
	Button btn_getCenterPoint;

	@ViewById(R.id.btn_movenowlocation)
	Button btn_moveCurrentPoint;

	@ViewById(R.id.v_centerPoint)
	View v_centerPoint;

	@Bean(CoachMarksImpl.class)
	CoachMarks coachMarks;

	@Bean(RequestSnowboxes.class)
	JsonRequest jsonSnowbox;

	@Pref
	AppPreference_ appPref;

	AnimationDrawable myLocationAnimation;

	private double standardLat = 37.537229;

	private double standardLng = 127.005515;

	private double standardDistance = 0.5d;

	private LocationManager locationManager;

	private String locationProvider;

	private Location location;

	private long buttonClickMilSecond = System.currentTimeMillis();

	private static final int GAP_ALLOW_CLICK_TIME = 1000;

	@AfterInject
	public void afterInject() {
		coachMarks.showCoachMark(getSherlockActivity(), CoachMarks.COACH_MARK_3, appPref.isShowINFOFragment());
		initLocationManager();
		setHasOptionsMenu(true);
	}

	public void initLocationManager() {
		locationManager = (LocationManager) getSherlockActivity().getSystemService(Context.LOCATION_SERVICE);
		Criteria criteria = new Criteria();
		criteria.setAccuracy(Criteria.ACCURACY_FINE);
		criteria.setAltitudeRequired(false);
		criteria.setBearingRequired(false);
		criteria.setCostAllowed(true);
		criteria.setPowerRequirement(Criteria.POWER_LOW);

		locationProvider = locationManager.getBestProvider(criteria, true);
		if (locationProvider == null) {
			Toast.makeText(getSherlockActivity(), "GPS 사용을 체크해주세요 .", Toast.LENGTH_LONG).show();
			startActivity(new Intent(android.provider.Settings.ACTION_LOCATION_SOURCE_SETTINGS));
			return;
		}
		location = locationManager.getLastKnownLocation(locationProvider);

		if (!locationManager.isProviderEnabled(locationProvider)
				&& locationManager.getLastKnownLocation(locationProvider) != null) {
			locationManager.requestLocationUpdates(locationProvider, 1000, 10, this);

		} else {
			criteria.setAccuracy(Criteria.ACCURACY_COARSE);
			locationProvider = locationManager.getBestProvider(criteria, true);
			location = locationManager.getLastKnownLocation(locationProvider);
			locationManager.requestLocationUpdates(locationProvider, 1000, 10, this);
		}

		geoManager.initContext(getSherlockActivity());
	}

	@UiThread
	public void processMarkPin(JSONObject listSnowRemoveBox) {
		try {
			JSONArray snowboxArray = listSnowRemoveBox.getJSONArray("ListSnowRemoveBox");
			int snowBoxSizeCount = snowboxArray.length();
			int nearSnowboxCount = 0;
			CoordPoint pt;
			CoordPoint ktmPt;
			mapView.removeAllPOIItems();

			for (int i = 0; i < snowBoxSizeCount; i++) {
				JSONObject jo = snowboxArray.getJSONObject(i);
				MapPOIItem poiItem1 = new MapPOIItem();
				poiItem1.setItemName(jo.getString("sbox_num"));
				pt = new CoordPoint(jo.getDouble("g2_xmin"), jo.getDouble("g2_ymin"));
				ktmPt = TransCoord.getTransCoord(pt, TransCoord.COORD_TYPE_WTM, TransCoord.COORD_TYPE_WGS84);

				if (particialDistance(ktmPt.y, ktmPt.x) > standardDistance) {
					continue;

				} else {
					poiItem1.setMapPoint(MapPoint.mapPointWithGeoCoord(ktmPt.y, ktmPt.x));
					poiItem1.setMarkerType(MapPOIItem.MarkerType.CustomImage);
					poiItem1.setCustomImageResourceId(R.drawable.location_mark);
					poiItem1.setShowAnimationType(MapPOIItem.ShowAnimationType.SpringFromGround);
					poiItem1.setShowCalloutBalloonOnTouch(true);
					poiItem1.setDraggable(false);
					poiItem1.setTag(jo.getInt("g2_id"));
					mapView.addPOIItem(poiItem1);
					nearSnowboxCount++;
				}
			}

			if (nearSnowboxCount == 0) {
				mapView.setMapCenterPoint(MapPoint.mapPointWithGeoCoord(standardLat, standardLng), true);
				Toast.makeText(getSherlockActivity(), "해당 구 500m내 위치한 제설함이 없습니다. 다른 위치를 검색해 주세요.", Toast.LENGTH_SHORT)
						.show();
			}
		} catch (JSONException je) {
			je.printStackTrace();
		}
	}

	@AfterViews
	public void afterView() {
		getSherlockActivity().getSupportActionBar().setTitle(R.string.actionbarTitleFind);
		mapView.setDaumMapApiKey(SnowtomsPreference.DAUM_MAP_API_KEY);
		mapView.setOpenAPIKeyAuthenticationResultListener(this);
		mapView.setMapViewEventListener(this);
		mapView.setPOIItemEventListener(this);
		mapView.setCurrentLocationEventListener(this);
		mapView.setMapType(MapView.MapType.Standard);
		mapView.setZoomLevel(4, true);
	}

	@Override
	public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
		super.onCreateOptionsMenu(menu, inflater);
	}

	private double particialDistance(double targetLat, double targetLng) {
		double result = 6378 * Math.acos(Math.cos(Math.toRadians(standardLat)) * Math.cos(Math.toRadians(targetLat))
				* Math.cos(Math.toRadians(targetLng) - Math.toRadians(standardLng))
				+ Math.sin(Math.toRadians(standardLat)) * Math.sin(Math.toRadians(targetLat)));
		return result;
	}

	@Click(R.id.btn_getcenterpoint)
	public void getCenterPoint() {
		GeoCoordinate centerPoint = mapView.getMapCenterPoint().getMapPointGeoCoord();
		if (System.currentTimeMillis() - buttonClickMilSecond > GAP_ALLOW_CLICK_TIME) {
			buttonClickMilSecond = System.currentTimeMillis();
			moveCenterPoint(centerPoint.latitude, centerPoint.longitude);
		}
	}

	@Click(R.id.btn_movenowlocation)
	public void moveCurrentLocation() {
		if (location != null) {
			if (System.currentTimeMillis() - buttonClickMilSecond > GAP_ALLOW_CLICK_TIME) {
				buttonClickMilSecond = System.currentTimeMillis();
				mapView.setMapCenterPoint(MapPoint.mapPointWithGeoCoord(location.getLatitude(), location.getLongitude()), true);
				moveCenterPoint(location.getLatitude(), location.getLongitude());
			}
		}
	}

	@Background
	public void moveCenterPoint(double lat, double lng) {
		String address = MapReverseGeoCoder.findAddressForMapPoint(SnowtomsPreference.DAUM_LOCAL_API_KEY,
				MapPoint.mapPointWithGeoCoord(lat, lng));
		String[] tempAddress = address.split(" ");
		String si = tempAddress[0];
		if (!si.equals("서울특별시")) {
			aSyncToastMessage("서울 외 지역에선 이용할 수 없습니다. 요청 된 지역은 " + si + "입니다.");
			return;
		}

		String gu = tempAddress[1];
		for (District cursorDistrict : RankFragment.districtArray) {

			if (cursorDistrict.getDistrictNameHangul().equals(gu)) {
				standardLat = lat;
				standardLng = lng;
				startHttpConnection(cursorDistrict);
				return;
			}
		}
		afterMoveCenterPoint(lat, lng);
	}

	@UiThread
	public void aSyncToastMessage(String message) {
		Toast.makeText(getSherlockActivity(), message, Toast.LENGTH_SHORT).show();
	}

	@UiThread
	public void afterMoveCenterPoint(double lat, double lng) {
		mapView.setMapCenterPointAndZoomLevel(MapPoint.mapPointWithGeoCoord(lat, lng), 2, true);
	}

	@Background
	public void searchDaumKeyword(String query) {
		try {
			afterSearch(addressSearchRequest.sendJsonRequest());
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (JSONException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@UiThread
	public void afterSearch(JSONObject resultJo) {
		Toast.makeText(getSherlockActivity(), resultJo.toString(), Toast.LENGTH_LONG).show();
	}

	@Background
	public void startHttpConnection(District selectedDistrict) {
		((RequestSnowboxes) jsonSnowbox).setDistrict(selectedDistrict);
		try {
			processMarkPin(jsonSnowbox.sendJsonRequest().getJSONObject("params"));
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (JSONException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void onCalloutBalloonOfPOIItemTouched(MapView arg0, MapPOIItem selectedItem) {
		// String[] chars = new String[] { "\'" + selectedItem.getItemName() +
		// "\' 제설함을 제보" };
		//
		// AlertDialog.Builder listBuilder = new
		// AlertDialog.Builder(getSherlockActivity());
		// listBuilder.setItems(chars, new DialogInterface.OnClickListener() {
		// public void onClick(DialogInterface dialog, int item) {
		// // Tempolary close
		// // ((MainActivity) getSherlockActivity()).movePostActivity(new
		// // PostActivityIntent(false, false, false, 2));
		// }
		// });
		// AlertDialog alertList = listBuilder.create();
		// alertList.show();
	}

	@Override
	public void onDraggablePOIItemMoved(MapView arg0, MapPOIItem arg1, MapPoint arg2) {
	}

	@Override
	public void onPOIItemSelected(MapView arg0, MapPOIItem mapPoitemPoint) {
	}

	@Override
	public void onMapViewCenterPointMoved(MapView arg0, MapPoint arg1) {
		btn_moveCurrentPoint.setVisibility(View.INVISIBLE);
		btn_getCenterPoint.setVisibility(View.INVISIBLE);
	}

	@Override
	public void onMapViewDoubleTapped(MapView arg0, MapPoint arg1) {
	}

	@Override
	public void onMapViewInitialized(MapView arg0) {
	}

	@Override
	public void onMapViewLongPressed(MapView arg0, MapPoint arg1) {
	}

	@Override
	public void onMapViewSingleTapped(MapView arg0, MapPoint arg1) {
		btn_moveCurrentPoint.setVisibility(View.VISIBLE);
		btn_getCenterPoint.setVisibility(View.VISIBLE);
	}

	@Override
	public void onMapViewZoomLevelChanged(MapView arg0, int arg1) {
	}

	@Override
	public void onDaumMapOpenAPIKeyAuthenticationResult(MapView mapView, int arg1, String message) {
		aSyncToastMessage(message);
	}

	@Override
	public boolean onQueryTextSubmit(String query) {
		return false;
	}

	@Override
	public boolean onQueryTextChange(String newText) {
		return false;
	}

	@Override
	public void onCurrentLocationDeviceHeadingUpdate(MapView arg0, float arg1) {
		Log.i("DAUMMAP",
				String.format("MapView onCurrentLocationDeviceHeadingUpdate: device heading = %f degrees", arg1));
	}

	@Override
	public void onCurrentLocationUpdate(MapView mapView, MapPoint mapPoint, float arg2) {
		Log.d("DAUMMAP",
				"Current location @ x : " + mapPoint.getMapPointGeoCoord().latitude + ", Y : "
						+ mapPoint.getMapPointGeoCoord().longitude);
	}

	@Override
	public void onCurrentLocationUpdateCancelled(MapView arg0) {

	}

	@Override
	public void onCurrentLocationUpdateFailed(MapView arg0) {
		Toast.makeText(getSherlockActivity(), "일시적으로 현재 위치를 찾을 수 없습니다. 다시 시도해 주세요.", Toast.LENGTH_SHORT).show();
	}

	@Override
	public void onLocationChanged(Location location) {
	}

	@Override
	public void onProviderDisabled(String provider) {
	}

	@Override
	public void onProviderEnabled(String provider) {
	}

	@Override
	public void onStatusChanged(String provider, int status, Bundle extras) {
	}

	@UiThread
	@SuppressWarnings("deprecation")
	public void startLogoAnimation() {
		myLocationAnimation = new AnimationDrawable();
		myLocationAnimation.addFrame(getResources().getDrawable(R.drawable.map_loacation_on), 500);
		myLocationAnimation.addFrame(getResources().getDrawable(R.drawable.map_loacation_off), 500);

		myLocationAnimation.setOneShot(false);
		btn_moveCurrentPoint.setBackgroundDrawable(myLocationAnimation);
		btn_moveCurrentPoint.post(new AnimationStater());
	}

	public class AnimationStater implements Runnable {
		@Override
		public void run() {
			myLocationAnimation.start();
		}

	}

	@UiThread
	public void stopLogoAnimation() {
		mapView.removeAllPOIItems();
		if (myLocationAnimation.isRunning()) {
			myLocationAnimation.stop();
		}
	}

	@Override
	public void onResume() {
		super.onResume();
		startLogoAnimation();
	}

	@Override
	public void onPause() {
		super.onPause();
		stopLogoAnimation();
		mapView.destroyDrawingCache();

	}
}
